#===-- Style_check.py - Simple style checking for llvm       *- Python -*-
#
#                     The LLVM Compiler Infrastructure
#
# This file is distributed under the University of Illinois Open Source
# License. See LICENSE.TXT for details.
#
#===----------------------------------------------------------------------

from optparse import OptionParser
import glob
import os
import re
import fnmatch

parser = OptionParser("usage: %prog arg1 arg2 ... argn [options]");
parser.add_option("", "--no-check-for-tabs", action="store_false",
     dest="doCheckForTabs",
     default = True, help="don't check for tabs")
parser.add_option("", "--no-check-line-length", action="store_false",
     dest="doCheckLineLength",
     default = True, help="don't check line length")
parser.add_option("", "--max-line-length", dest="maxLineLength",
                       default=80, type="int",
                       help="specify maximum line length [default 80]")
parser.add_option("", "--no-check-whitespace-at-eol", action="store_false",
     dest="doCheckWhitespaceAtEol",
     default = True, help="don't check for whitespace at the end of a line")
parser.add_option("", "--print-filenames-only", action="store_true",
     dest="doPrintFilenamesOnly",
     default = False, help="only print the filename(s) where errors were found")
parser.add_option("", "--recursive", action="store_true",
     dest="doRecursive",
     default = False, help="rescursively walk subdirectories")
parser.add_option("", "--name-matches", dest="nameMatches",
                       default="", type="string",
                       help="name must match the following")
parser.add_option("", "--not-name-matches", dest="notNameMatches",
                       default="", type="string",
                       help="name must not match the following")
(options, args) = parser.parse_args()


doCheckForTabs=options.doCheckForTabs
doCheckLineLength=options.doCheckLineLength
maxLineLength=options.maxLineLength
doCheckWhitespaceAtEol=options.doCheckWhitespaceAtEol
doPrintFilenamesOnly=options.doPrintFilenamesOnly
doRecursive=options.doRecursive
nameMatches=options.nameMatches;
notNameMatches=options.notNameMatches;

root_dot_fname = ".style_check"


# nameMatches_re = re.compile(nameMatches, re.VERBOSE)

def checkTabs(f, lineNum, line):
  column = 0;
  for c in line:
    column = column + 1
    if c == '\t':
      if (doPrintFilenamesOnly):
        print f.name
      else:
        print "tab at line=", lineNum, "column=", column, f.name
      return True
  return False

def checkLineLength(f, lineNum, line):
  if len(line) > maxLineLength + 1:
    if (doPrintFilenamesOnly):
      print f.name
    else:
      print line,
      print "line too long=", lineNum, "len=", len(line) - 1, f.name
    return True
  return False

def checkWhitespaceBeforeEOL(f, lineNum, line):
  if len(line) <= 1:
    return
  if line[len(line)-2].isspace():
    if (doPrintFilenamesOnly):
      print f.name
    else:
      print "whitespace at end of line=", lineNum, "len=", len(line) - 1, f.name
    return True
  return False

def goodFileName(f):
  fname = os.path.basename(f)
  if nameMatches !="" and  (fnmatch.fnmatch(fname, nameMatches) == False):
    return False
  if notNameMatches != "" and (fnmatch.fnmatch(fname, notNameMatches) == True):
    return False
  return True
 
def doOneFile(fname, topLevel):
  if os.path.isdir(fname):
    if topLevel or doRecursive:
      # print "in recursive ", fname
      for root, dirs, files  in os.walk(fname):
        # print "root ", root, "dirs ", dirs, "files ", files
        for d in dirs:
          doOneFile(root + "/" + d, False)
        for f in files:
          if goodFileName(f):
            doOneFile(root + "/" + f, False)
  else:
    if not goodFileName(fname):
      return
    f = open(fname, 'r')
    lineNum = 0;
    for line in f:
      lineNum = lineNum + 1
      if doCheckLineLength:
        errorFound = checkLineLength(f, lineNum, line)
        if errorFound and doPrintFilenamesOnly:
          break;
      if doCheckForTabs:
        errorFound = checkTabs(f, lineNum, line)
        if errorFound and doPrintFilenamesOnly:
          break;
      if doCheckWhitespaceAtEol:
        errorFound = checkWhitespaceBeforeEOL(f, lineNum, line)
        if errorFound and doPrintFilenamesOnly:
          break;

for x in args:
  g = glob.glob(x)
  for y in g:
    doOneFile(y, True)

